package com.luhuiguo.cms.server.webdav;

import org.apache.commons.vfs.FileObject;
import org.apache.commons.vfs.FileSystemException;
import org.apache.commons.vfs.FileType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.bradmcevoy.http.Resource;
import com.bradmcevoy.http.ResourceFactory;
import com.bradmcevoy.http.SecurityManager;
import com.ettrema.http.fs.LockManager;
import com.ettrema.http.fs.NullSecurityManager;
import com.newatlanta.appengine.vfs.provider.GaeVFS;

/**
 * @author will
 * @date Nov 7, 2009 1:20:07 AM
 */
public class GaeResourceFactory implements ResourceFactory {

    private static final Logger logger = LoggerFactory.getLogger(GaeResourceFactory.class);

    SecurityManager securityManager;

    LockManager lockManager;

    Long maxAgeSeconds;

    String contextPath;

    boolean allowDirectoryBrowsing;

    String defaultPage;

    public GaeResourceFactory() {
        logger.debug("setting default configuration...");
        setSecurityManager(new NullSecurityManager());
    }

    public GaeResourceFactory(SecurityManager securityManager) {
        setSecurityManager(securityManager);
    }

    public GaeResourceFactory(SecurityManager securityManager, String contextPath) {
        setSecurityManager(securityManager);
        setContextPath(contextPath);
    }

    @Override
    public Resource getResource(String host, String path) {
        Resource resource;
        path = stripContext(path);

        try {
            final FileObject fileObject = GaeVFS.resolveFile("gae://" + path);
            if (fileObject.exists()) {
                if (fileObject.getType() == FileType.FOLDER) {
                    resource = new GaeDirectoryResource(host, this, fileObject);
                    return resource;
                } else {
                    resource = new GaeFileResource(host, this, fileObject);
                    return resource;
                }
            } else {
                return null;
            }
        } catch (FileSystemException e) {
            logger.warn(e.getMessage(), e);
            // e.printStackTrace();
            return null;
        } finally {
        }
    }

    public Long maxAgeSeconds(GaeResource resource) {
        return maxAgeSeconds;
    }

    public String getSupportedLevels() {
        return "1,2";
    }

    public String getRealm(String host) {
        return securityManager.getRealm(host);
    }

    public void setSecurityManager(SecurityManager securityManager) {
        if (securityManager != null) {
            logger.debug("securityManager: {}", securityManager.getClass());
        } else {
            logger.warn("Setting null SecurityManager. This WILL cause null pointer exceptions");
        }
        this.securityManager = securityManager;
    }

    public SecurityManager getSecurityManager() {
        return securityManager;
    }

    public void setMaxAgeSeconds(Long maxAgeSeconds) {
        this.maxAgeSeconds = maxAgeSeconds;
    }

    public Long getMaxAgeSeconds() {
        return maxAgeSeconds;
    }

    public LockManager getLockManager() {
        return lockManager;
    }

    public void setLockManager(LockManager lockManager) {
        this.lockManager = lockManager;
    }

    public String getContextPath() {
        return contextPath;
    }

    public void setContextPath(String contextPath) {
        this.contextPath = contextPath;
    }

    public boolean isAllowDirectoryBrowsing() {
        return allowDirectoryBrowsing;
    }

    public void setAllowDirectoryBrowsing(boolean allowDirectoryBrowsing) {
        this.allowDirectoryBrowsing = allowDirectoryBrowsing;
    }

    public String getDefaultPage() {
        return defaultPage;
    }

    public void setDefaultPage(String defaultPage) {
        this.defaultPage = defaultPage;
    }

    private String stripContext(String path) {
        if (this.contextPath != null && contextPath.length() > 0) {
            path = path.replaceFirst('/' + contextPath, "");
            logger.debug("stripped context: {}", path);
            return path;
        } else {
            return path;
        }
    }

}
